﻿    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.IdentityModel.Tokens;

    
namespace Security.Authorizations
{
    
           public  static partial class Authorizations
           {



            public static string GetUserFromTicket(string userTicket)
            {
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(userTicket);

                if (string.IsNullOrEmpty(userTicket))
                    throw new SecurityTokenException("Unknown Username");

                if (ticket.Expired)
                    throw new SecurityTokenException("Expired ticket");

                return ticket.Name;
            }

            public static string GetUserTicket(string username)
            {
                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(username, true, 30);
                return FormsAuthentication.Encrypt(ticket);
            }

            public static string GetUserTicket()
            {
                if (!(HttpContext.Current.User == null))
                {
                    if (HttpContext.Current.User.Identity.IsAuthenticated)
                    {
                        if (HttpContext.Current.User.Identity.GetType() == typeof(FormsIdentity))
                        {
                            FormsIdentity fi = (FormsIdentity)HttpContext.Current.User.Identity;
                            return FormsAuthentication.Encrypt(fi.Ticket);
                        }
                    }
                }

                throw new System.Security.Authentication.InvalidCredentialException();
            }


            public static Permissions SetPermissions(string username, string[] scopeNames, string readOperation, string createOperation, string deleteOperation,
                string updateOperation, string executeOperation, params string[] extendedOperations)
            {

               var operations = createOperationNamesArray(readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations);

                string[] authOperations = Authorizations.AccessCheck(username, operations.ToArray(), scopeNames);

                Permissions permissions = createPermissionFromAuthorizationsResult(readOperation, createOperation, updateOperation, deleteOperation, executeOperation, extendedOperations, authOperations);

                return permissions;
            }

            public static Permissions SetPermissionsFromAnyScope(string username, string scopeNameFilterToMatch, string readOperation, string createOperation, string deleteOperation,
            string updateOperation, string executeOperation, params string[] extendedOperations)
            {

                var operations = createOperationNamesArray(readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations);

                var authOperations = Authorizations.AccessCheckAnyScope(username, operations.ToArray(), scopeNameFilterToMatch);

                Permissions permissions = createPermissionFromAuthorizationsResult(readOperation, createOperation, updateOperation, deleteOperation, executeOperation, extendedOperations, authOperations);
                
                return permissions;
            }

            private static Permissions createPermissionFromAuthorizationsResult(string readOperation, string createOperation, string updateOperation, string deleteOperation, string executeOperation, string[] extendedOperations, string[] authOperations)
            {
                Permissions permissions = new Permissions();

                permissions.canRead = authOperations.Contains(readOperation);
                permissions.canDelete = authOperations.Contains(deleteOperation);
                permissions.canCreate = authOperations.Contains(createOperation);
                permissions.canUpdate = authOperations.Contains(updateOperation);
                permissions.canExecute = authOperations.Contains(executeOperation);

                if (extendedOperations != null)
                {
                    foreach (var item in extendedOperations)
                    {
                        if (authOperations.Contains(item))
                            permissions.addPermission(item);
                    }
                }
                return permissions;
            }

            private static string[] createOperationNamesArray(string readOperation, string createOperation, string deleteOperation, string updateOperation, string executeOperation, string[] extendedOperations)
            {
                List<string> operations = new List<string>();
                if (!string.IsNullOrEmpty(readOperation)) operations.Add(readOperation);
                if (!string.IsNullOrEmpty(createOperation)) operations.Add(createOperation);
                if (!string.IsNullOrEmpty(deleteOperation)) operations.Add(deleteOperation);
                if (!string.IsNullOrEmpty(updateOperation)) operations.Add(updateOperation);
                if (!string.IsNullOrEmpty(executeOperation)) operations.Add(executeOperation);
                if (extendedOperations != null) operations.AddRange(extendedOperations);
                return operations.ToArray();
            }                    

            //public static bool AccessCheckFromTicket(string userTicket, string[] scopeNames, string operationName)
            //{
            //    string username = getUserFromTicket(userTicket);
            //    return AccessCheckFromUserName(getUserFromTicket(userTicket), scopeNames, operationName);
            //}

            //public static bool acccessCheckFromTicketFromAnyScope(string userTicket, string operationName)
            //{
            //    string username = getUserFromTicket(userTicket);
            //    string[] scopeNames = getScopeNames(null, username);
            //    return accessCheckFromUserName(getUserFromTicket(userTicket), scopeNames, operationName);
            //}

            //public static bool AccessCheckFromUserName(string username, string[] scopeNames, string operationName)
            //{
            //    if (string.IsNullOrEmpty(operationName))
            //        return false;

            //    return Authorizations.AccessCheck(username, operationName, scopeNames);
            //}

            //public static string[] accessCheckFromUserName(string username, string[] operationNames, string[] scopeNames)
            //{
            //    return Authorizations.AccessCheck(username, operationNames, scopeNames);
            //}

            public static Scope[] SetScopesWithFilter(string username, string scopeFilter, string readOperation, string createOperation, string deleteOperation,
                string updateOperation, string executeOperation, params string[] extendedOperations)
            {
                string[] scopeNames = getScopeNames(scopeFilter, username);

                List<Scope> scopes = new List<Scope>();
                foreach (var scopeName in scopeNames)
                {
                    scopes.Add(new Scope(
                        scopeName,
                        SetPermissions(username, new[] { scopeName }, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations)));
                }

                scopes.Add(new Scope(
                       "Any",
                       SetPermissionsFromAnyScope(username, scopeFilter, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations)));

                return scopes.ToArray();
            }

            public static Scope[] SetScopesWithFilterFromUserTicket(string userTicket, string scopeFilter, string readOperation, string createOperation, string deleteOperation,
                string updateOperation, string executeOperation, params string[] extendedOperations)
            {
                string username = GetUserFromTicket(userTicket);
                return SetScopesWithFilter(username, scopeFilter, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations);
            }

            private static string[] getScopeNames(string scopeFilter, string username)
            {
                string[] scopeNames = string.IsNullOrEmpty(scopeFilter) ? Authorizations.GetScopesForUser(username) : Authorizations.GetScopesForUser(username, scopeFilter);
                return scopeNames;
            }

            public static Scope SetFromAnyScopeFromUserTicket(string userTicket, string readOperation, string createOperation, string deleteOperation, string updateOperation, string executeOperation, params string[] extendedOperations)
            {
                string username = GetUserFromTicket(userTicket);
                return new Scope(
                        "Any",
                        SetPermissionsFromAnyScope(username, null, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations));

            }

            public static Scope SetFromAnyScope(string username, string readOperation, string createOperation, string deleteOperation, string updateOperation, string executeOperation, params string[] extendedOperations)
            {
                return new Scope(
                        "Any",
                        SetPermissionsFromAnyScope(username, null, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations));
            } 


            public static Scope[] SetScopes(string username, string readOperation, string createOperation, string deleteOperation, string updateOperation, string executeOperation, params string[] extendedOperations)
            {
                return SetScopesWithFilter(username, null, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations);
            }

            public static Scope[] SetScopesFromUserTicket(string userTicket, string readOperation, string createOperation, string deleteOperation,
                string updateOperation, string executeOperation, params string[] extendedOperations)
            {
                return SetScopesWithFilterFromUserTicket(userTicket, null, readOperation, createOperation, deleteOperation, updateOperation, executeOperation, extendedOperations);
            }

            //public static string[] getUsersInRole(string roleName, string scopeName)
            //{
            //    return Authorizations.GetUsersInRole(roleName, scopeName);
            //}
        }
    }
